package com.shop.util.pay;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.shop.util.http.HttpUtil;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
public class PayUtil {

    private static final String applicationName = "念她";
    private static final String alipayNotifyUrl = "http://111.230.93.21:8090/callBack/alipayCallback";
    private static final String spbillCreateIp = "111.230.93.21";
    private static final String weixinNotifyUrl = "http://111.230.93.21:8090/callBack/wxPayCallBack";

    /**
     * 支付宝支付
     *
     * @param orderNo            订单号
     * @param payAmount          支付金额
     * @param projectName        项目名称
     * @param alipay_appid       支付宝appId
     * @param alipay_private_key 支付宝秘钥
     * @param alipay_public_key  支付宝公钥
     * @return
     * @throws Exception
     */
    public static String alipayCreateOrder(String orderNo, BigDecimal payAmount, String projectName, String alipay_appid, String alipay_private_key, String alipay_public_key) throws Exception {

        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                alipay_appid.trim(),
                alipay_private_key.trim(), "json",
                "utf-8",
                alipay_public_key.trim(),
                "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(applicationName + "-" + projectName);
        model.setSubject(projectName);
        model.setOutTradeNo(orderNo);
        model.setTimeoutExpress("30m");
        model.setTotalAmount(payAmount.toString());
//		model.setTotalAmount("0.01");
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(alipayNotifyUrl);
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

            return response.getBody();//就是orderString 可以直接给客户端请求，无需再做处理。
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 支付宝支付
     *
     * @param map
     * @return
     * @throws Exception
     */
    public static String alipayCreateOrder(Map<String, String> map) throws Exception {

        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                map.get("alipay_appid").trim(),
                map.get("alipay_private_key").trim(), "json",
                "utf-8",
                map.get("alipay_public_key").trim(),
                "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(map.get("applicationName") + "-" + map.get("body"));
        model.setSubject(map.get("body"));
        model.setOutTradeNo(map.get("orderNo"));
        model.setTimeoutExpress("30m");
        model.setTotalAmount(map.get("payAmount"));
//		model.setTotalAmount("0.01");
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(map.get("alipayNotifyUrl"));
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            log.info("支付宝请求返回====" + response.getBody());
            return response.getBody();//就是orderString 可以直接给客户端请求，无需再做处理。
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 微信支付
     *
     * @param body    描述类容
     * @param orderNo 订单号
     * @param money   支付金额
     * @param appId
     * @param mchId
     * @param key
     * @return
     */
    public static Map<String, Object> wxPay(String body, String orderNo, Integer money, String appId, String mchId, String key) {
        WXPayConfigUtil config;
        try {
            config = WXPayConfigUtil.getInstance(appId, mchId, key);
            WXPay wxpay = new WXPay(config);

            HashMap<String, String> data = new HashMap<String, String>();
            data.put("body", applicationName + "-" + body);
            data.put("out_trade_no", orderNo);
            data.put("fee_type", "CNY");
            data.put("total_fee", money.toString());
            data.put("spbill_create_ip", spbillCreateIp);
            data.put("notify_url", weixinNotifyUrl);
            data.put("trade_type", "APP");

            System.out.println(data);
            Map<String, String> r = wxpay.unifiedOrder(data);

            System.out.println(r);

            if ("SUCCESS".equals(r.get("result_code")) && "OK".equals(r.get("return_msg"))) {
                // 无序
                Map<String, String> map = new HashMap<>();
                map.put("appid", config.getAppID());
                map.put("partnerid", config.getMchID());
                map.put("prepayid", r.get("prepay_id"));
                map.put("package", "Sign=WXPay");
                map.put("noncestr", WXPayUtil.generateNonceStr());
                map.put("timestamp", (System.currentTimeMillis() / 1000) + "");
                map.put("sign", WXPayUtil.generateSignature(map, config.getKey()));
                return new HashMap<String, Object>() {
                    private static final long serialVersionUID = 1L;

                    {
                        putAll(map);
                    }
                };
            } else {
                return new HashMap<String, Object>();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<String, Object>();
    }

    /**
     * 微信支付
     *
     * @param m
     * @return
     */
    public static Map<String, Object> wxPay(Map<String, String> m) {
        WXPayConfigUtil config;
        try {
            config = WXPayConfigUtil.getInstance(m.get("wxAppId"), m.get("wxMchId"), m.get("wxMchIdKey"));
            WXPay wxpay = new WXPay(config);

            HashMap<String, String> data = new HashMap<>();
            data.put("body", m.get("applicationName") + "-" + m.get("body"));
            data.put("out_trade_no", m.get("orderNo"));
            data.put("fee_type", "CNY");
            data.put("total_fee", m.get("money"));
            data.put("spbill_create_ip", m.get("spbillCreateIp"));
            data.put("notify_url", m.get("weixinNotifyUrl"));
            data.put("trade_type", "APP");

            Map<String, String> r = wxpay.unifiedOrder(data);
            log.info("微信请求回调====" + r.toString());

            if ("SUCCESS".equals(r.get("result_code")) && "OK".equals(r.get("return_msg"))) {
                // 有序插入
                LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
                map.put("appid", config.getAppID());
                map.put("noncestr", WXPayUtil.generateNonceStr());
                map.put("package", "Sign=WXPay");
                map.put("partnerid", r.get("prepay_id"));
                map.put("prepayid", r.get("prepay_id"));
                map.put("timestamp", (System.currentTimeMillis() / 1000) + "");
                map.put("sign", WXPayUtil.generateSignature(map, config.getKey()));
                return new HashMap<String, Object>() {
                    private static final long serialVersionUID = 1L;

                    {
                        putAll(map);
                    }
                };
            } else {
                return new HashMap<>();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<>();
    }


    public static JSONObject isAccessTokenIsInvalid(String appId, String secret, String weixinCode) {
        // 解密参数
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + secret + "&code=" + weixinCode + "&grant_type=authorization_code";
        String result = HttpUtil.httpClentString(url, "");
        log.info("微信token:" + result);
        JSONObject tokenJsonObject = JSONObject.parseObject(result);
        if (!tokenJsonObject.isEmpty() && tokenJsonObject.get("openid") != null) {
            String access_token = tokenJsonObject.getString("access_token");
            String openId = tokenJsonObject.getString("openid");
            url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openId + "&lang=zh_CN";
            result = HttpUtil.httpClentString(url, "");
            JSONObject userObject = JSONObject.parseObject(result);
            if (userObject.get("openid") == null) {
                return null;
            }
            log.info("微信用户信息:" + result);
            return userObject;
        }
        return null;
    }


}
